/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "../Widget.h"
#include "事件处理.h"


static float64 gdur;
static clock_t g时间start = clock();
static clock_t g时间end;


static uint8 g键盘以按下键[4] = {};



static bool f_执行键盘事件(S_键盘键位映射* mk, const uint8* 键盘按键状态) {
	uint8 bit = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}
		else {
			if (g键盘以按下键[k]) {
				mk->记录 |= 1 << k;
			}
		}
	}

	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}

	if (bit && mk->记录 == bit) {
		mk->记录 = 0;
		return true;
	}

	if (控制键全部释放) {
		mk->记录 = 0;
	}
	return false;
}

bool f_event_执行鼠标事件(S_鼠标键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {
	uint8 bit = 0;
	mk->记录 = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}

		if (mk->鼠标状态[k]) {
			bit |= 1 << k + 4;

			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << k + 4;
			}
		}
	}

	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}

	if (bit && mk->记录 == bit) {
		mk->记录 = 0;
		return true;
	}

	if (控制键全部释放) {
		mk->记录 = 0;
	}
	return false;
}

static bool f_执行拖拽事件(S_拖拽键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {

	uint8 bit = 0;
	mk->记录 = 0;

	switch (mk->拖放状态)
	{
	case E_拖放状态::e_拖放_开始: {
		mk->拖放状态 = E_拖放状态::e_拖放_进行;
		break;
	}
	case E_拖放状态::e_拖放_进行: {
		break;
	}
	case E_拖放状态::e_拖放_结束: {
		break;
	}
	default:
		break;
	}

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}
		//cout << "mk->鼠标按键[k] = " << mk->鼠标按键[k] << endl;
		if (mk->鼠标状态[k]) {
			bit |= 1 << k + 4;

			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << k + 4;
			}
		}
	}


	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}


	if (bit && mk->记录 == bit) {
		//计时 = time_开始计时();
		//mk->记录 = 0;
		mk->状态 = 0;
		return true;
	}

	if (控制键全部释放) {
		mk->记录 = 0;
		mk->状态 = 0;
	}

	return false;
}





bool f_键盘单个按键状态(const uint8* 键盘按键状态, uint8 key, uint8 状态) {
	return (键盘按键状态[key] & 状态);
	//return (键盘按键状态[key] == 状态);
}



bool f_执行双击事件(S_鼠标双击键位映射* mk, uint8* 键盘按键状态, uint8* 鼠标按键状态) {
	uint8 bit = 0;
	mk->记录 = 0;

	for (uint8 k = 0; k < 4; ++k) {
		if (mk->键盘按键[k]) {
			bit |= 1 << k;

			if (f_键盘单个按键状态(键盘按键状态, mk->键盘按键[k], mk->键盘状态[k])) {
				mk->记录 |= 1 << k;
			}
		}

		if (mk->鼠标状态[k]) {
			bit |= 1 << k + 4;

			if (mk->鼠标状态[k] & 鼠标按键状态[mk->鼠标按键[k]]) {
				mk->记录 |= 1 << k + 4;
			}
		}
	}

	bool 控制键全部释放 = true;
	for (uint8 k = 0; k < 4; ++k) {
		if (键盘按键状态[mk->键盘按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
		if (键盘按键状态[mk->鼠标按键[k]] != DEF_按键状态_准备) {
			控制键全部释放 = false;
		}
	}

	if (bit && mk->记录 == bit) {
		mk->记录 = 0;

		if (mk->开始计时 && !mk->结束计时) {
			mk->结束计时 = clock();
			auto gdur = (double)(mk->结束计时 - mk->开始计时);
			if (gdur > S_UI主题::ui_双击时间间隔) {
				mk->开始计时 = 0;
			}
			else {
				mk->开始计时 = 0;
				mk->结束计时 = 0;
				return true;
			}
		}
		else {
			mk->开始计时 = clock();
		}
	}

	if (控制键全部释放) {
		mk->记录 = 0;
		
		mk->结束计时 = clock();
		auto gdur = (double)(mk->结束计时 - mk->开始计时);
		if (gdur > S_UI主题::ui_双击时间间隔) {
			mk->开始计时 = 0;
		}
		mk->结束计时 = 0;
	}
	return false;
}







bool f_event_执行键位绑定事件(C_Widget& w, C_Widget管理& gm, const S_输入环境& input) {
	uint32 键位映射num = w.m_键位映射.size();
	auto* 键位映射keys = w.m_键位映射.data();
	for (uint8 i = 0; i < 键位映射num; ++i) {
		switch (键位映射keys[i]->m_Type) {
		case E_键位映射类型::e_键映射类型_键盘: {
			S_键盘键位映射* km = (S_键盘键位映射*)键位映射keys[i];
			if (f_执行键盘事件(km, input.m_Key.Keys状态)) {
				if (!(km->发生组件)) km->发生组件 = &w;
				if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
					continue;
				}
				return true;
			}
			break;
		}
		case E_键位映射类型::e_键映射类型_鼠标: {
			S_鼠标键位映射* km = (S_鼠标键位映射*)键位映射keys[i];
			if (f_event_执行鼠标事件(km, input.m_Key.Keys状态, gm.鼠标按键状态)) {
				if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
					continue;
				}
				return true;
			}
			break;
		}
		case E_键位映射类型::e_键映射类型_拖拽: {
			S_拖拽键位映射* km = (S_拖拽键位映射*)键位映射keys[i];
			if (((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY) {
				if (f_执行拖拽事件(km, input.m_Key.Keys状态, gm.鼠标按键状态)) {
					km->状态 = 1;
					if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
						continue;
					}
					return true;
				}
			}
			break;
		}
		case E_键位映射类型::e_键映射类型_双击: {
			S_鼠标双击键位映射* km = (S_鼠标双击键位映射*)键位映射keys[i];
			if (f_执行双击事件(km, input.m_Key.Keys状态, gm.鼠标按键状态)) {
				if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
					continue;
				}
				return true;
			}
			break;
		}
		}
	}
	return false;
}

/*void f_event_组件时间执行(C_Widget管理* gm, C_Widget* w, C_Widget* 上一次焦点组件, E_事件是否传递 事件是否传递) {
	if (事件是否传递 == E_事件是否传递::e_事件传递_继续 && 上一次焦点组件 != w) {
		if (上一次焦点组件 != 0) {
			if (i < gm->m_上一次焦点组件数量) {
				if (gm->m_上一次焦点组件[i]->mf_鼠标离开) gm->m_上一次焦点组件[i]->mf_鼠标离开(gm->m_上一次焦点组件[i], C_Widget::g_鼠标);
			}
		}

		if (w->mf_鼠标进入) {
			w->mf_鼠标进入(w, C_Widget::g_鼠标);
		}

		//记录以执行鼠标进入事件
		gm->m_上一次焦点组件[i] = w;
	}



	bool 不向下传递 = false;

	//鼠标左键事件
	{
		if (gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_按下 && gm->鼠标左键按下传递) {

			gm->鼠标左键按下传递 = w->mf_鼠标按键按下(w, E_鼠标按钮::e_鼠标左键);



			//==================== 双击开始计时 =====================
			g时间end = clock();
			gdur = (double)(g时间end - g时间start);
			gdur = (gdur * 1000 / CLOCKS_PER_SEC);

			if (gdur > S_UI主题::ui_双击时间间隔) {
				g时间start = clock();
				g_上一轮焦点组件 = w;
				gm->执行鼠标点击 = true;
			}
			else if (g_上一轮焦点组件 == w) {
				if (w->mf_鼠标按键双击) {
					gm->鼠标左键按下传递 |= w->mf_鼠标按键双击(w, E_鼠标按钮::e_鼠标左键);
					g双击时间 = 0;
				}
				gm->执行鼠标点击 = false;
			}



			if (gm->m_当前操作部件 == 0) gm->m_当前操作部件 = w;

			if (C_Widget::g_焦点数量 - i == 1) {
				f_ui_文本部件完成输入(w);
			}


			//==================== 开始拖放事件 ====================
			if (w->mf_拖拽 && gm->拖放状态 == DEF_拖放状态_准备) {
				gm->拖放状态 = DEF_拖放状态_开始拖放;
				gm->m_当前拖拽部件 = w;
			}
		}


		if (gm->鼠标按键状态[E_Input_鼠标按键::e_左键] == DEF_按键状态_放开 && gm->鼠标左键放开传递) {
			gm->鼠标左键放开传递 = w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标左键);

			if (gm->m_当前拖拽部件 && gm->m_当前拖拽部件->mf_结束拖拽 && gm->拖放状态 == DEF_拖放状态_拖放) {
				gm->m_当前拖拽部件->mf_结束拖拽(gm->m_当前拖拽部件, w, gm->m_拖放数据);
				if (w->mf_结束拖拽 && w != gm->m_当前拖拽部件) w->mf_结束拖拽(w, gm->m_当前拖拽部件, gm->m_拖放数据);
			}
			else {
				if (!鼠标移动了 && gm->m_当前操作部件 == w) {
					w->mf_鼠标按键点击(w, E_鼠标按钮::e_鼠标左键);
					gm->m_当前操作部件 = nullptr;
				}
			}

			gm->m_当前拖拽部件 = nullptr;
			gm->拖放状态 = DEF_拖放状态_准备;
			gm->执行鼠标点击 = false;
		}
	}

	//鼠标右键事件
	{
		if (gm->鼠标按键状态[E_Input_鼠标按键::e_右键] == DEF_按键状态_按下) {
			w->mf_鼠标按键按下(w, E_鼠标按钮::e_鼠标右键);
		}
		else if (gm->鼠标按键状态[E_Input_鼠标按键::e_右键] == DEF_按键状态_放开) {
			w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标右键);
		}
	}

	//鼠标中键事件
	{
		if (gm->鼠标按键状态[E_Input_鼠标按键::e_中键] == DEF_按键状态_按下) {
			w->mf_鼠标按键按下(w, E_鼠标按钮::e_鼠标中键);
		}
		else if (gm->鼠标按键状态[E_Input_鼠标按键::e_中键] == DEF_按键状态_放开) {
			w->mf_鼠标按键放开(w, E_鼠标按钮::e_鼠标中键);
		}
	}

	//鼠标移动
	{
		if (((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY) {
			w->mf_鼠标移动(w, Mouse);
		}
	}

	//鼠标滚轮
	{
		if (((S_鼠标属性*)input.m_鼠标)->lZ && w->mf_鼠标滚轮) {
			w->mf_鼠标滚轮(w, C_Widget::g_鼠标);
		}
	}



	if (gm->键盘按键向下传递) {
		if (w->mf_键盘按键敲击) gm->键盘按键向下传递 = w->mf_键盘按键敲击(w, input.m_Key);
	}



	uint32 键位映射num = w->m_键位映射.size();
	auto* 键位映射keys = w->m_键位映射.data();
	for (uint8 i = 0; i < 键位映射num; ++i) {
		switch (键位映射keys[i]->m_Type) {
		case E_键位映射类型::e_键映射类型_键盘: {
			S_键盘键位映射* km = (S_键盘键位映射*)键位映射keys[i];
			if (f_执行键盘事件(km, input.m_Key.Keys状态)) {
				km->event(w, km->状态);
			}
			break;
		}
		case E_键位映射类型::e_键映射类型_鼠标: {
			S_鼠标键位映射* km = (S_鼠标键位映射*)键位映射keys[i];
			if (f_执行鼠标事件(km, input.m_Key.Keys状态, gm->鼠标按键状态)) {
				if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
					continue;
				}
				goto To_按键状态设置;
			}
			break;
		}
		case E_键位映射类型::e_键映射类型_拖拽: {
			S_拖拽键位映射* km = (S_拖拽键位映射*)键位映射keys[i];
			if (((S_鼠标属性*)input.m_鼠标)->lX || ((S_鼠标属性*)input.m_鼠标)->lY) {
				if (f_执行拖拽事件(km, input.m_Key.Keys状态, gm->鼠标按键状态)) {
					km->状态 = 1;
					if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
						continue;
					}
					goto To_按键状态设置;
				}
			}
			break;
		}
		case E_键位映射类型::e_键映射类型_双击: {
			S_鼠标双击键位映射* km = (S_鼠标双击键位映射*)键位映射keys[i];
			if (f_执行双击事件(km, input.m_Key.Keys状态, gm->鼠标按键状态)) {
				if (km->event(km->发生组件, km->状态) == E_事件是否传递::e_事件传递_继续) {
					continue;
				}
				goto To_按键状态设置;
			}
			break;
		}
		}
	}
}*/













